#include <iostream>
#include <sstream>
#include <functional>
#include <vector>
#include <algorithm>

#include "types.hpp"
#include "FileHelper.hpp"

using namespace std;

extern string getLex(int, int);
extern MainScanerMap mainScanerMap[];
extern FileHelper fh;

// 子扫描器, 超搜到条件end就结束
string superScanner(function<bool(char)> end)
{
  char nextInput;
  stringstream sstream;

  while ((nextInput = fh.next()) != EOF)
  {
    if (end(nextInput))
    {
      sstream << nextInput;
    }
    else
    {
      fh.back();
      break;
    }
  }
  return sstream.str();
}

void Scanner()
{
  vector<string> idList, intList;

  char nextInput;
  stringstream outstream;

  while ((nextInput = fh.next()) != EOF)
  {
    if (nextInput == '#')
      break;
    else if (nextInput == ' ' || nextInput == '\n')
      continue;
    else if (nextInput == '+')
    {
      char nextInput2 = fh.next();
      if (nextInput2 == '=')
      {
        outstream << getLex(2, 3);
      }
      else
      {
        outstream << getLex(2, 0);
        fh.back();
      }
    }

    else if (nextInput == '*')
    {
      char nextInput2 = fh.next();
      if (nextInput2 == '=')
      {
        outstream << getLex(2, 4);
      }
      else
      {
        outstream << getLex(2, 1);
        fh.back();
      }
    }

    else if (isdigit(nextInput))
    {
      // 判断为数字后回退一位，交给超搜处理器处理
      fh.back();

      auto fn = [](char c) -> bool
      { return isdigit(c); };

      string value = superScanner(fn);

      auto valuePosition = find(intList.begin(), intList.end(), value);
      if (valuePosition == intList.end())
      {
        intList.push_back(value);
      }
      valuePosition = find(intList.begin(), intList.end(), value);
      int index = distance(intList.begin(), valuePosition);

      outstream << getLex(5, index);
    }

    else if (isalpha(nextInput) || nextInput == '_')
    {
      // 判断为 字母或者下划线 后回退一位，交给超搜处理器处理
      fh.back();

      auto fn = [](char c) -> bool
      { return (isalpha(c) || c == '_'); };

      string value = superScanner(fn);

      if (value == "int")
      {
        outstream << getLex(1, 0);
        continue;
      }

      if (value == "main")
      {
        outstream << getLex(1, 1);
        continue;
      }

      if (value == "return")
      {
        outstream << getLex(1, 2);
        continue;
      }

      auto valuePosition = find(idList.begin(), idList.end(), value);
      if (valuePosition == idList.end())
      {
        idList.push_back(value);
      }
      valuePosition = find(idList.begin(), idList.end(), value);
      int index = distance(idList.begin(), valuePosition);

      outstream << getLex(4, index);
    }

    else
    {
      for (int i = 0; i < 7; i++)
      {
        if (nextInput == mainScanerMap[i].token)
        {
          outstream << mainScanerMap[i].output;
          break;
        }
      }
    }
  }

  std::cout << outstream.str() << endl;

  std::cout << "identifieres:";
  for (auto i = idList.begin(); i != idList.end(); ++i)
  {
    std::cout << *i << " ";
  }
  std::cout << endl;

  std::cout << "Unsigned_integer:";
  for (auto i = intList.begin(); i != intList.end(); ++i)
  {
    std::cout << *i << " ";
  }
  std::cout << endl;
}
